#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
配置模块 - 用于加载和管理配置
"""

import os
import sys
import json
import logging
from typing import Dict, Any, Optional, List

# 默认配置
DEFAULT_CONFIG = {
    "tcp": {
        "buffer_size": 8192,
        "timeout": 300,
        "max_connections": 100,
        "min_connections": 10
    },
    "udp": {
        "buffer_size": 8192,
        "timeout": 120,
        "max_clients": 100
    },
    "security": {
        "allowed_ips": [],  # 空列表表示允许所有IP
        "blacklist_ips": []
    },
    "logging": {
        "level": "INFO",
        "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
        "file": "port_forwarder.log"
    },
    "monitoring": {
        "enabled": True,
        "stats_interval": 60  # 统计信息更新间隔（秒）
    },
    # 添加转发规则配置
    "forwarding_rules": [
        # 默认规则示例
        # {
        #     "name": "示例HTTP转发",
        #     "local_port": 8080,
        #     "remote_host": "example.com",
        #     "remote_port": 80,
        #     "protocol": "tcp",
        #     "enabled": true
        # }
    ],
    # 添加默认转发配置
    "default_forwarding": {
        "local_port": 8080,
        "remote_host": "localhost",
        "remote_port": 80,
        "protocol": "tcp"
    }
}

def get_application_path():
    """
    获取应用程序路径，兼容打包后的环境
    
    Returns:
        str: 应用程序路径
    """
    # 判断是否是打包后的环境
    if getattr(sys, 'frozen', False):
        # 如果是打包后的环境，使用 sys.executable 的目录
        return os.path.dirname(sys.executable)
    else:
        # 如果是开发环境，使用脚本文件的目录
        return os.path.dirname(os.path.abspath(__file__))

# 配置文件路径
CONFIG_FILE = os.path.join(get_application_path(), "port_forwarder.json")

# 添加配置缓存
_config_cache = None
_config_last_modified = 0

def load_config() -> Dict[str, Any]:
    """
    加载配置文件，如果不存在则创建默认配置文件
    使用缓存避免频繁读取文件
    
    Returns:
        Dict[str, Any]: 配置字典
    """
    global _config_cache, _config_last_modified
    
    try:
        # 检查文件是否存在
        if os.path.exists(CONFIG_FILE):
            # 检查文件是否被修改
            current_mtime = os.path.getmtime(CONFIG_FILE)
            
            # 如果缓存存在且文件未被修改，直接返回缓存
            if _config_cache and current_mtime <= _config_last_modified:
                return _config_cache
                
            # 读取配置文件
            with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
                config = json.load(f)
                
                # 合并默认配置，确保所有必要的配置项都存在
                merged_config = DEFAULT_CONFIG.copy()
                for section, values in config.items():
                    if section in merged_config and isinstance(merged_config[section], dict):
                        merged_config[section].update(values)
                    else:
                        merged_config[section] = values
                
                # 更新缓存
                _config_cache = merged_config
                _config_last_modified = current_mtime
                
                return merged_config
        else:
            # 创建默认配置文件
            try:
                with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
                    json.dump(DEFAULT_CONFIG, f, indent=4)
                
                # 更新缓存
                _config_cache = DEFAULT_CONFIG.copy()
                _config_last_modified = os.path.getmtime(CONFIG_FILE)
                
                return _config_cache
            except Exception as e:
                logging.error(f"创建默认配置文件失败: {e}")
                return DEFAULT_CONFIG
    except Exception as e:
        logging.error(f"加载配置文件失败: {e}")
        return DEFAULT_CONFIG

def get_config_value(section: str, key: str, default: Any = None) -> Any:
    """
    获取特定配置值
    
    Args:
        section: 配置部分
        key: 配置键
        default: 默认值
        
    Returns:
        Any: 配置值
    """
    config = load_config()
    return config.get(section, {}).get(key, default)

def get_forwarding_rules() -> List[Dict[str, Any]]:
    """
    获取所有启用的转发规则
    
    Returns:
        List[Dict[str, Any]]: 转发规则列表
    """
    config = load_config()
    rules = config.get("forwarding_rules", [])
    # 只返回启用的规则
    return [rule for rule in rules if rule.get("enabled", True)]

def get_default_forwarding() -> Dict[str, Any]:
    """
    获取默认转发配置
    
    Returns:
        Dict[str, Any]: 默认转发配置
    """
    config = load_config()
    return config.get("default_forwarding", {})

def save_config(config: Dict[str, Any]) -> bool:
    """
    保存配置到文件
    
    Args:
        config: 配置字典
        
    Returns:
        bool: 保存成功返回True，否则返回False
    """
    global _config_cache, _config_last_modified
    
    try:
        with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
            json.dump(config, f, indent=4)
        
        # 更新缓存
        _config_cache = config
        _config_last_modified = os.path.getmtime(CONFIG_FILE)
        
        return True
    except Exception as e:
        logging.error(f"保存配置文件失败: {e}")
        return False

def add_forwarding_rule(name: str, local_port: int, remote_host: str, 
                        remote_port: int, protocol: str = "tcp", 
                        enabled: bool = True) -> bool:
    """
    添加新的转发规则
    
    Args:
        name: 规则名称
        local_port: 本地端口
        remote_host: 远程主机
        remote_port: 远程端口
        protocol: 协议类型
        enabled: 是否启用
        
    Returns:
        bool: 添加成功返回True，否则返回False
    """
    config = load_config()
    
    # 创建新规则
    new_rule = {
        "name": name,
        "local_port": local_port,
        "remote_host": remote_host,
        "remote_port": remote_port,
        "protocol": protocol,
        "enabled": enabled
    }
    
    # 添加到规则列表
    rules = config.get("forwarding_rules", [])
    rules.append(new_rule)
    config["forwarding_rules"] = rules
    
    # 保存配置
    return save_config(config)


def set_config_file(file_path):
    """设置配置文件路径"""
    global CONFIG_FILE, _config_cache, _config_last_modified
    CONFIG_FILE = file_path
    _config_cache = None
    _config_last_modified = 0